import "babel-polyfill";

export var PriorityQueueTemplate = function(prior_to = (x, y) => x > y) {
    return class {
        constructor() {
            var data = this.data = Array.prototype.slice.call(arguments);
            var length = data.length;
            for (let position = length >>> 1; --position >= 0;) {
                let index = position;
                let x = data[index];
                while (length >= 2 * index + 3) {
                    let child = 2 * index + 2;
                    if (length > child + 1 && prior_to(data[child + 1], data[child])) {
                        ++child;
                    }
                    if (prior_to(data[child], x)) {
                        data[index] = data[child];
                        index = child;
                    } else {
                        break;
                    }
                }
                data[index] = x;
            }
        }

        get [Symbol.toStringTag]() {
            return "PriorityQueue";
        }

        get size() {
            return this.data.length;
        }

        push() {
            var data = this.data;
            for (let x of arguments) {
                let index = data.length;
                while (index) {
                    var parent_index = (index - 1) >>> 1;
                    if (prior_to(x, data[parent_index])) {
                        data[index] = data[parent_index];
                    } else {
                        break;
                    }
                    index = parent_index;
                }
                data[index] = x;
            }
            return this.size;
        }
        pop() {
            var data = this.data;
            if (data.length <= 1) {
                return data.pop();
            } else {
                let x = data.pop();
                let y = data[0];
                let index = 0;
                let length = data.length;
                while (length >= 2 * index + 2) {
                    let child = 2 * index + 1;
                    if (length > child + 1 && prior_to(data[child + 1], data[child])) {
                        ++child;
                    }
                    if (prior_to(data[child], x)) {
                        data[index] = data[child];
                        index = child;
                    } else {
                        break;
                    }
                }
                data[index] = x;
                return y;
            }
        }
        top() {
            return this.data[0];
        }
    };
};

export default PriorityQueueTemplate();
